<template>
  <div class="file-attachment">
    <div v-for="(file, index) in props.files" :key="index" class="file-item">
      <!-- 图片文件显示缩略图 -->
      <div v-if="isImageFile(file)" class="file-thumbnail">
        <img :src="file.url"
             :alt="file.name"
             @click="handlePreview(file)"/>
      </div>

      <!-- 非图片文件显示图标 -->
      <div v-else class="file-icon clickable" @click="handleDownload(file)">
        <slot name="file-icon" :file="file">
          <FilePdfOutlined v-if="file.type === 'pdf'"/>
          <FileWordOutlined v-else-if="file.type === 'doc' || file.type === 'docx'"/>
          <FileExcelOutlined v-else-if="file.type === 'xls' || file.type === 'xlsx'"/>
          <FileZipOutlined v-else-if="file.type === 'zip' || file.type === 'rar' || file.type === '7z'"/>
          <FileTextOutlined v-else-if="file.type === 'txt' || file.type === 'md'"/>
          <FilePptOutlined v-else-if="file.type === 'ppt' || file.type === 'pptx'"/>
          <AudioOutlined v-else-if="['mp3','wav','aac'].includes(file.type)"/>
          <FileOutlined v-else/>
        </slot>
      </div>

      <div class="file-info">
        <!-- 文件名支持换行显示 -->
        <a-tooltip placement="topLeft" :title="file.name">
          <div class="file-name">
            {{ formatFileName(file.name) }}
          </div>
        </a-tooltip>
        <div class="file-size">{{ formatFileSize(file.size) }}</div>
      </div>

      <div class="file-actions" v-if="hasDownloadHandler">
        <a-button type="text" @click="handleDownload(file)">
          <DownloadOutlined/>
        </a-button>
      </div>
    </div>

    <!-- 图片预览模态框 -->
    <slot name="preview" :previewImage="previewImage" :visible="previewVisible" :close="closePreview">
      <a-modal
          :visible="previewVisible"
          :footer="null"
          @cancel="closePreview"
      >
        <img style="width: 100%" :src="previewImage" alt=""/>
      </a-modal>
    </slot>
  </div>
</template>

<script lang="ts" setup>
import {ref, computed, getCurrentInstance} from 'vue';
import {
  FileOutlined,
  FilePdfOutlined,
  FileWordOutlined,
  FileExcelOutlined,
  FileZipOutlined,
  FileTextOutlined,
  DownloadOutlined,
  FilePptOutlined,
  AudioOutlined,
} from '@ant-design/icons-vue';
import Color from "color";

interface FileItem {
  name: string;
  type: string;
  size: number;
  url?: string;
}

const props = defineProps({
  files: {
    type: Array as () => FileItem[],
    default: () => [],
    required: true,
    validator: (value: any[]) => {
      return value.every(item =>
          item.name &&
          typeof item.name === 'string' &&
          item.type &&
          typeof item.type === 'string' &&
          typeof item.size === 'number'
      );
    }
  },
  iconColor: {
    type: String,
    default: '#1890ff',
  },
  lightenAmount: {
    type: Number,
    default: 0.2 // 默认变亮20%
  },
});

const emit = defineEmits(['download']);

let previewVisible = ref(false);
const previewImage = ref('');
const previewLoading = ref(false);

// 检查是否是图片文件
const isImageFile = (file: FileItem) => {
  return file && ['png', 'jpeg', 'jpg', 'gif', 'webp'].includes(file.type.toLowerCase());
};

const closePreview = () => {
  previewVisible.value = false;
};

// 格式化文件名显示
const formatFileName = (name: string) => {
  if (!name) return '';

  // 优先截断中间部分保留前后内容
  if (name.length > 30) {
    const front = name.substring(0, 12);
    const end = name.substring(name.length - 12);
    return `${front}...${end}`;
  }
  return name;
};

// 图片预览处理
const handlePreview = (file: FileItem) => {
  if (!file.url) {
    return;
  }

  previewLoading.value = true;
  previewImage.value = file.url;
  previewVisible.value = true;
};

const formatFileSize = (bytes: number) => {
  if (bytes === 0) return '0 Bytes';
  const k = 1024;
  const sizes = ['Bytes', 'KB', 'MB', 'GB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
};

const handleDownload = (file: FileItem) => {
  emit('download', file);
};

const instance = getCurrentInstance();
const hasDownloadHandler = computed(() => {
  return !!instance?.vnode?.props?.onDownload;
});

const hoverColor = computed(() => {
  try {
    const color = typeof props.iconColor === 'string' && props.iconColor.match(/^[a-z]+$/i)
        ? Color().keyword(props.iconColor)
        : Color(props.iconColor);
    return color.lighten(props.lightenAmount).hex();
  } catch {
    // 如果颜色解析失败，使用默认的变亮颜色
    return '#ff7875';
  }
});

defineExpose({
  hoverColor,
})
</script>

<style lang="less" scoped>
.file-attachment {
  width: 100%;
  max-width: 600px;
  margin-top: 10px;
}

.file-item {
  display: flex;
  align-items: center;
  padding: 12px;
  border: 1px solid #e8e8e8;
  border-radius: 4px;
  margin-bottom: 8px;
  background-color: #fafafa;
  transition: all 0.2s;
  height: 72px;

  &:hover {
    border-color: #d9d9d9;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  }
}

.file-thumbnail {
  position: relative;
  width: 48px;
  height: 48px;
  margin-right: 12px;
  cursor: pointer;
  background-color: #f0f0f0;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  flex-shrink: 0;

  img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: 4px;
  }
}

.file-icon {
  font-size: 24px;
  margin-right: 12px;
  min-width: 24px;
  color: v-bind('props.iconColor');
  flex-shrink: 0;

  &.clickable {
    cursor: pointer;

    &:hover {
      color: v-bind('hoverColor');
    }
  }
}

.file-info {
  flex: 1;
  min-width: 0;
  margin-right: 12px;
  overflow: hidden;
}

.file-name {
  font-size: 14px;
  margin-bottom: 4px;
  color: #595959;
  overflow: hidden;
  text-overflow: ellipsis;
  line-height: 1.4;
}

.file-size {
  color: #8c8c8c;
  font-size: 12px;
  line-height: 1.4;
}

.file-actions {
  flex-shrink: 0;
}

.preview-loading {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 300px;
}
</style>